package com.ctgu.tengyun.controller.saleorder;

import com.ctgu.tengyun.bean.errorcode.SaleOrderErrorCode;
import com.ctgu.tengyun.bean.request.SparePartApplyRequest;
import com.ctgu.tengyun.bean.response.SparePartSaleListResponse;
import com.ctgu.tengyun.bean.response.SparePartSaleOrder;
import com.ctgu.tengyun.domain.*;
import com.ctgu.tengyun.exception.ErrorCodeException;
import com.ctgu.tengyun.exception.RequestValidateException;
import com.ctgu.tengyun.manager.SaleOrderManager;
import com.ctgu.tengyun.service.customer.CustomerInfoService;
import com.ctgu.tengyun.service.saleorder.SaleOrderConfirmService;
import com.ctgu.tengyun.service.saleorder.SaleOrderRecordService;
import com.ctgu.tengyun.service.sparepart.SparePartInfoService;
import com.ctgu.tengyun.service.user.SysUserService;
import com.ctgu.tengyun.util.*;
import com.google.common.collect.ImmutableMap;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * Created by liaoweizhi on 2019/8/7.
 */
@RestController
@RequestMapping("/v1/sale_order/spare_part")
public class SaleOrderSparePartController {

    @Resource
    private SparePartInfoService sparePartInfoService;
    @Resource
    private SaleOrderManager saleOrderManager;
    @Resource
    private SaleOrderRecordService saleOrderRecordService;
    @Resource
    private CustomerInfoService customerInfoService;
    @Resource
    private SysUserService sysUserService;
    @Resource
    private SaleOrderConfirmService saleOrderConfirmService;

    @RequestMapping("/apply")
    public Object sparePartApply(HttpServletRequest httpServletRequest, @RequestBody SparePartApplyRequest request) {
        Validator.assertHasFields(!StringUtils.isEmpty(request.getContactName()), "contactName is required.");
        Validator.assertHasFields(!StringUtils.isEmpty(request.getContactNo()), "contactNo is required.");
        Validator.assertHasFields(!StringUtils.isEmpty(request.getPartNo()), "partNo is required.");
        Validator.assertHasFields(!StringUtils.isEmpty(request.getReceiveAddress()), "receive address is required.");
        Validator.assertHasFields(null != request.getSaleNum(), "sale num is required.");
        Validator.validateGt(request.getSaleNum(), 0);

        Long userId = RequestExtract.getUserId(httpServletRequest);
        String partNo = request.getPartNo();
        SparePartInfo sparePartInfo = sparePartInfoService.selectByPartNo(partNo);
        Validator.assertResourceFound(null != sparePartInfo, "spare part not found, partNo:" + partNo);

        if (request.getSaleNum() > sparePartInfo.getStockNum()) {
            throw new ErrorCodeException(SaleOrderErrorCode.spare_part_stock_not_enough,
                    SaleOrderErrorCode.spare_part_stock_not_enough.getHintMessage() + sparePartInfo.getStockNum());
        }

        return ImmutableMap.of("id", saleOrderManager.apply(request, userId, sparePartInfo, partNo));
    }

    @RequestMapping("/sale_list")
    public SparePartSaleListResponse sparePartSaleList(HttpServletRequest request) {
        Integer pageNo = ParameterTool.getParameterInteger(request, "pageNo", 1);
        Integer pageSize = ParameterTool.getParameterInteger(request, "pageSize", 10);
        String partNo = ParameterTool.getParameterString(request, "partNo", null);
        String contactNo = ParameterTool.getParameterString(request, "contactNo", null);
        Integer orderStatus = ParameterTool.getParameterInteger(request, "orderStatus", null);

        Validator.validateGt(pageNo, 0);
        Validator.validateBetweenIn(pageSize, 0, 1000);
        if (null != orderStatus) {
            SaleOrderStatus.valueOf(orderStatus);
        }

        Integer totalCount = saleOrderRecordService.countSaleOrder(partNo, contactNo, orderStatus);
        List<SaleOrderRecord> saleOrderRecordList = Collections.emptyList();
        if (totalCount > 0) {
            saleOrderRecordList = saleOrderRecordService.selectSaleOrder(partNo, contactNo, orderStatus, pageNo, pageSize);
        }

        Set<Long> recordIdSet = CollectionsUtil.getComposerIdSet(saleOrderRecordList, SaleOrderRecord.ID_COMPOSER);
        Set<Long> customerIdSet = CollectionsUtil.getComposerIdSet(saleOrderRecordList, SaleOrderRecord.CUSTOMER_ID_COMPOSER);
        Set<Long> operationIdSet = CollectionsUtil.getComposerIdSet(saleOrderRecordList, SaleOrderRecord.OPERATION_USER_ID_COMPOSER);

        List<SaleOrderConfirm> saleOrderConfirmList = saleOrderConfirmService.selectBySaleRecordIds(recordIdSet);
        List<CustomerInfo> customerInfoList = customerInfoService.selectByIds(customerIdSet);
        List<SysUser> sysUserList = sysUserService.selectByIds(operationIdSet);

        Map<Long, SaleOrderConfirm> saleRecordIdMap = CollectionsUtil.mapComposerId(saleOrderConfirmList, SaleOrderConfirm.SALE_RECORD_ID_COMPOSER);
        Map<Long, CustomerInfo> customerIdMap = CollectionsUtil.mapComposerId(customerInfoList, CustomerInfo.ID_COMPOSER);
        Map<Long, SysUser> idSysUserMap = CollectionsUtil.mapComposerId(sysUserList, SysUser.ID_COMPOSER);

        SparePartSaleListResponse response = new SparePartSaleListResponse();
        response.setTotalCount(totalCount);
        response.setTotalPage((int) Math.ceil(totalCount / (double) pageSize));

        List<SparePartSaleOrder> sparePartSaleOrderList = new ArrayList<>(saleOrderRecordList.size());
        for (SaleOrderRecord saleOrderRecord : saleOrderRecordList) {
            SparePartSaleOrder sparePartSaleOrder = new SparePartSaleOrder();
            sparePartSaleOrder.setSaleOrderRecord(saleOrderRecord);
            sparePartSaleOrder.setSaleOrderConfirm(saleRecordIdMap.get(saleOrderRecord.getId()));
            sparePartSaleOrder.setOperationUser(idSysUserMap.get(saleOrderRecord.getOperationUserId()));
            sparePartSaleOrder.setCustomerInfo(customerIdMap.get(saleOrderRecord.getCustomerId()));

            sparePartSaleOrderList.add(sparePartSaleOrder);
        }
        response.setSaleOrderList(sparePartSaleOrderList);

        return response;
    }

    @RequestMapping("/sale_detail/{saleRecordId}")
    public SparePartSaleOrder sparePartSaleList(@PathVariable Long saleRecordId) {
        SaleOrderRecord saleOrderRecord = saleOrderRecordService.selectByPrimaryKey(saleRecordId);
        Validator.assertResourceFound(null != saleOrderRecord, "sale order record not found, saleRecordId:" + saleOrderRecord);

        SaleOrderConfirm saleOrderConfirm = saleOrderConfirmService.selectBySaleRecordId(saleOrderRecord.getId());
        CustomerInfo customerInfo = customerInfoService.selectByPrimaryKey(saleOrderRecord.getCustomerId());
        SysUser sysUser = sysUserService.selectByPrimaryKey(saleOrderRecord.getOperationUserId());

        SparePartSaleOrder sparePartSaleOrder = new SparePartSaleOrder();
        sparePartSaleOrder.setSaleOrderRecord(saleOrderRecord);
        sparePartSaleOrder.setSaleOrderConfirm(saleOrderConfirm);
        sparePartSaleOrder.setOperationUser(sysUser);
        sparePartSaleOrder.setCustomerInfo(customerInfo);

        return sparePartSaleOrder;
    }

    @PostMapping("/confirm")
    public void confirm(@RequestBody SaleOrderConfirm request) {
        Validator.assertHasFields(null != request.getId(), "confirm id is required");
        Validator.assertHasFields(null != request.getIsSupport() || null != request.getOrderStatus(),
                "isSupport or orderStatus is required");

        Long confirmId = request.getId();
        Integer isSupport = request.getIsSupport();
        Integer orderStatus = request.getOrderStatus();
        String remark = request.getRemark();

        SaleOrderConfirm confirm = saleOrderConfirmService.selectByPrimaryKey(confirmId);
        Validator.assertResourceFound(null != confirm, "sale order confirm info not found, id:" + confirmId);

        if (null != isSupport) {
            BooleanStatus.valueOf(isSupport);
        }
        if (null != orderStatus) {
            SaleOrderStatus saleOrderStatus = SaleOrderStatus.valueOf(orderStatus);
            if (SaleOrderStatus.cancelled.equals(SaleOrderStatus.valueOf(confirm.getOrderStatus())) &&
                    !SaleOrderStatus.cancelled.equals(saleOrderStatus)) {
                throw new RequestValidateException("sale order has cancelled");
            }
        }

        SaleOrderConfirm updateRequest = new SaleOrderConfirm();
        updateRequest.setId(confirmId);
        updateRequest.setIsSupport(isSupport);
        updateRequest.setOrderStatus(orderStatus);
        updateRequest.setVersion(confirm.getVersion());
        updateRequest.setRemark(remark);

        saleOrderConfirmService.updateByPrimaryKeySelective(updateRequest);
    }

}
